/*     */ package com.zimbra.cs.dav.carddav;
/*     */ 
/*     */ import com.google.common.io.Closeables;
/*     */ import com.zimbra.common.mailbox.ContactConstants;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.dav.DavContext;
/*     */ import com.zimbra.cs.dav.DavElements.CardDav;
/*     */ import com.zimbra.cs.dav.resource.AddressObject;
/*     */ import com.zimbra.cs.dav.resource.AddressbookCollection;
/*     */ import com.zimbra.cs.gal.GalSearchControl;
/*     */ import com.zimbra.cs.gal.GalSearchParams;
/*     */ import com.zimbra.cs.gal.GalSearchResultCallback;
/*     */ import com.zimbra.cs.index.ContactHit;
/*     */ import com.zimbra.cs.index.SortBy;
/*     */ import com.zimbra.cs.index.ZimbraHit;
/*     */ import com.zimbra.cs.index.ZimbraQueryResults;
/*     */ import com.zimbra.cs.mailbox.Contact;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxIndex;
/*     */ import com.zimbra.soap.type.GalSearchType;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collection;
/*     */ import java.util.Collections;
/*     */ import java.util.EnumSet;
/*     */ import java.util.HashMap;
/*     */ import java.util.HashSet;
/*     */ import org.dom4j.QName;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public abstract class Filter
/*     */ {
/*     */   protected String mName;
/*     */   protected boolean mIsNotDefinedSet;
/*     */   protected HashSet<PropFilter> mProps;
/*     */   protected HashSet<ParamFilter> mParams;
/*     */   protected TextMatch mTextMatch;
/*     */   protected Filter mEnclosingFilter;
/*     */   
/*     */   public Filter(org.dom4j.Element elem)
/*     */   {
/*  77 */     this.mProps = new HashSet();
/*  78 */     this.mParams = new HashSet();
/*  79 */     this.mName = elem.attributeValue("name");
/*  80 */     parse(elem);
/*     */   }
/*     */   
/*     */ 
/*  84 */   public String getName() { return this.mName; }
/*     */   
/*     */   private static enum MappingType {
/*  87 */     simple,  structured;
/*     */     
/*     */     private MappingType() {} }
/*     */   
/*     */   private static final class AttrMapping { public String name;
/*     */     public Filter.MappingType type;
/*     */     
/*  94 */     public static AttrMapping createSimple(String n, String attr) { AttrMapping m = new AttrMapping();
/*  95 */       m.type = Filter.MappingType.simple;
/*  96 */       m.name = n;
/*  97 */       m.contactAttr = attr;
/*  98 */       Filter.sAttrMappings.put(n, m);
/*  99 */       return m;
/*     */     }
/*     */     
/* 102 */     public static AttrMapping createStructured(String n, String... args) { AttrMapping m = new AttrMapping();
/* 103 */       m.type = Filter.MappingType.structured;
/* 104 */       m.name = n;
/* 105 */       m.structures = new HashMap();
/* 106 */       int pos = 0;
/* 107 */       while (pos <= args.length - 2) {
/* 108 */         m.structures.put(args[pos], new String[] { args[(pos + 1)] });
/* 109 */         pos += 2;
/*     */       }
/* 111 */       Filter.sAttrMappings.put(n, m);
/* 112 */       return m;
/*     */     }
/*     */     
/* 115 */     public static AttrMapping createStructured(String n) { AttrMapping m = new AttrMapping();
/* 116 */       m.type = Filter.MappingType.structured;
/* 117 */       m.name = n;
/* 118 */       m.structures = new HashMap();
/* 119 */       Filter.sAttrMappings.put(n, m);
/* 120 */       return m;
/*     */     }
/*     */     
/* 123 */     public void addSubType(String k, String... vals) { if (this.type == Filter.MappingType.simple)
/* 124 */         return;
/* 125 */       String[] v = new String[vals.length];
/* 126 */       int i = 0;
/* 127 */       for (String val : vals)
/* 128 */         v[(i++)] = val;
/* 129 */       this.structures.put(k, v);
/*     */     }
/*     */     
/* 132 */     public String[] getAttrs() { if (this.type == Filter.MappingType.simple)
/* 133 */         return new String[] { this.contactAttr };
/* 134 */       HashSet<String> ret = new HashSet();
/* 135 */       for (String[] val : this.structures.values())
/* 136 */         Collections.addAll(ret, val);
/* 137 */       return (String[])ret.toArray(new String[0]);
/*     */     }
/*     */     
/* 140 */     public String[] getAttrs(String key) { if (this.type == Filter.MappingType.simple)
/* 141 */         return new String[] { this.contactAttr };
/* 142 */       return (String[])this.structures.get(key);
/*     */     }
/*     */     
/*     */     public String contactAttr;
/*     */     public HashMap<String, String[]> structures;
/*     */   }
/*     */   
/* 149 */   private static final HashMap<String, AttrMapping> sAttrMappings = new HashMap();
/* 150 */   static { AttrMapping m = AttrMapping.createStructured("FN");
/* 151 */     m.addSubType("name", new String[] { ContactConstants.A_fullName, ContactConstants.A_firstName, ContactConstants.A_lastName });
/* 152 */     AttrMapping.createSimple("NICKNAME", ContactConstants.A_nickname);
/* 153 */     AttrMapping.createSimple("TITLE", ContactConstants.A_jobTitle);
/* 154 */     AttrMapping.createSimple("NOTE", ContactConstants.A_notes);
/* 155 */     AttrMapping.createStructured("ADR", new String[] { "home", ContactConstants.A_homeStreet, "work", ContactConstants.A_workStreet });
/* 156 */     AttrMapping.createStructured("URL", new String[] { "home", ContactConstants.A_homeURL, "work", ContactConstants.A_workURL });
/*     */     
/* 158 */     m = AttrMapping.createStructured("TEL", new String[] { "car", ContactConstants.A_carPhone, "cell", ContactConstants.A_mobilePhone, "pager", ContactConstants.A_pager, "other", ContactConstants.A_otherPhone });
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 164 */     m.addSubType("work", new String[] { ContactConstants.A_workPhone, ContactConstants.A_workPhone2 });
/* 165 */     m.addSubType("home", new String[] { ContactConstants.A_homePhone, ContactConstants.A_homePhone2 });
/* 166 */     m.addSubType("fax", new String[] { ContactConstants.A_homeFax, ContactConstants.A_workFax });
/*     */     
/* 168 */     m = AttrMapping.createStructured("EMAIL");
/* 169 */     m.addSubType("internet", new String[] { ContactConstants.A_email, ContactConstants.A_email2, ContactConstants.A_email3 });
/*     */     
/* 171 */     m = AttrMapping.createStructured("ORG");
/* 172 */     m.addSubType("work", new String[] { ContactConstants.A_company, ContactConstants.A_department });
/*     */   }
/*     */   
/*     */   public String getNameAsContactAttr() {
/* 176 */     return this.mName;
/*     */   }
/*     */   
/*     */   protected void parse(org.dom4j.Element elem) {
/* 180 */     for (Object o : elem.elements()) {
/* 181 */       if ((o instanceof org.dom4j.Element)) {
/* 182 */         org.dom4j.Element e = (org.dom4j.Element)o;
/* 183 */         QName name = e.getQName();
/* 184 */         if ((canHavePropFilter()) && (name.equals(DavElements.CardDav.E_PROP_FILTER))) {
/* 185 */           this.mProps.add(new PropFilter(e));
/* 186 */         } else if ((canHaveParamFilter()) && (name.equals(DavElements.CardDav.E_PARAM_FILTER))) {
/* 187 */           this.mParams.add(new ParamFilter(e, this));
/* 188 */         } else if (name.equals(DavElements.CardDav.E_TEXT_MATCH)) {
/* 189 */           this.mTextMatch = new TextMatch(e, this);
/* 190 */         } else if (name.equals(DavElements.CardDav.E_IS_NOT_DEFINED)) {
/* 191 */           this.mIsNotDefinedSet = true;
/*     */         } else
/* 193 */           ZimbraLog.dav.info("unrecognized filter " + name.getNamespaceURI() + ":" + name.getName());
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public Collection<AddressObject> match(DavContext ctxt, AddressbookCollection folder) {
/* 199 */     return null;
/*     */   }
/*     */   
/*     */   public boolean mIsNotDefinedSet() {
/* 203 */     return this.mIsNotDefinedSet;
/*     */   }
/*     */   
/*     */   protected boolean runTextMatch(String text) {
/* 207 */     boolean matched = true;
/* 208 */     return matched;
/*     */   }
/*     */   
/* 211 */   protected boolean canHavePropFilter() { return true; }
/* 212 */   protected boolean canHaveParamFilter() { return true; }
/*     */   
/*     */   public static enum MatchType {
/* 215 */     equals,  contains,  starts_with,  ends_with;
/*     */     
/*     */     private MatchType() {}
/* 218 */     public static MatchType fromString(String s) { try { if (s != null) {
/* 219 */           return valueOf(s.replace('-', '_'));
/*     */         }
/*     */       } catch (IllegalArgumentException e) {}
/* 222 */       return contains;
/*     */     }
/*     */   }
/*     */   
/*     */   public static class TextMatch extends Filter {
/*     */     private String mText;
/*     */     private boolean mNegate;
/*     */     private Filter.MatchType mMatch;
/*     */     
/*     */     private class Callback extends GalSearchResultCallback {
/*     */       DavContext ctxt;
/*     */       ArrayList<AddressObject> result;
/*     */       
/*     */       public Callback(ArrayList<AddressObject> ctxt, GalSearchParams result) {
/* 236 */         super();
/* 237 */         this.ctxt = ctxt;
/* 238 */         this.result = result;
/*     */       }
/*     */       
/*     */       public com.zimbra.common.soap.Element handleContact(Contact c)
/*     */       {
/*     */         try {
/* 244 */           this.result.add(new AddressObject(this.ctxt, c));
/*     */         } catch (ServiceException e) {
/* 246 */           ZimbraLog.dav.error("can't include gal search result", e);
/*     */         }
/* 248 */         return null;
/*     */       }
/*     */     }
/*     */     
/* 252 */     public TextMatch(org.dom4j.Element elem, Filter parent) { super();
/* 253 */       this.mEnclosingFilter = parent;
/*     */       
/* 255 */       this.mNegate = elem.attributeValue("negate-condition", "no").equals("yes");
/* 256 */       this.mText = elem.getText();
/* 257 */       this.mMatch = Filter.MatchType.fromString(elem.attributeValue("match-type"));
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */     public Collection<AddressObject> match(DavContext ctxt, AddressbookCollection folder)
/*     */     {
/* 264 */       ArrayList<AddressObject> result = new ArrayList();
/* 265 */       StringBuilder search = new StringBuilder();
/* 266 */       if (this.mNegate)
/* 267 */         search.append("!");
/* 268 */       Filter.AttrMapping mapping = (Filter.AttrMapping)Filter.sAttrMappings.get(this.mEnclosingFilter.getName().toUpperCase());
/* 269 */       if (mapping == null)
/* 270 */         return result;
/* 271 */       String[] attrs = mapping.getAttrs();
/* 272 */       search.append("(");
/* 273 */       boolean first = true;
/* 274 */       String key; for (key : attrs) {
/* 275 */         if (!first)
/* 276 */           search.append(" OR ");
/* 277 */         search.append("#").append(key).append(":");
/* 278 */         if ((this.mMatch == Filter.MatchType.contains) || (this.mMatch == Filter.MatchType.ends_with))
/* 279 */           search.append("*");
/* 280 */         search.append(this.mText);
/* 281 */         if ((this.mMatch == Filter.MatchType.contains) || (this.mMatch == Filter.MatchType.starts_with))
/* 282 */           search.append("*");
/* 283 */         first = false;
/*     */       }
/* 285 */       search.append(")");
/* 286 */       String filter = search.toString();
/* 287 */       ZimbraLog.dav.debug("Search Filter: %s", new Object[] { filter });
/* 288 */       ZimbraQueryResults zqr = null;
/*     */       try {
/* 290 */         Mailbox mbox = ctxt.getTargetMailbox();
/* 291 */         if (mbox == null) {
/* 292 */           ZimbraLog.dav.debug("Can't get target mailbox for %s", new Object[] { ctxt.getUser() });
/* 293 */           return result;
/*     */         }
/* 295 */         zqr = mbox.index.search(ctxt.getOperationContext(), filter, EnumSet.of(MailItem.Type.CONTACT), SortBy.NAME_ASC, 100);
/*     */         
/* 297 */         while (zqr.hasNext()) {
/* 298 */           hit = zqr.getNext();
/* 299 */           if ((hit instanceof ContactHit))
/* 300 */             result.add(new AddressObject(ctxt, ((ContactHit)hit).getContact()));
/*     */         }
/*     */       } catch (Exception e) {
/*     */         ZimbraHit hit;
/* 304 */         ZimbraLog.dav.warn("can't get target mailbox", e);
/* 305 */         return result;
/*     */       } finally {
/* 307 */         Closeables.closeQuietly(zqr);
/*     */       }
/* 309 */       boolean includeGal = true;
/* 310 */       if (includeGal) {
/* 311 */         StringBuilder query = new StringBuilder();
/* 312 */         if ((this.mMatch == Filter.MatchType.contains) || (this.mMatch == Filter.MatchType.ends_with))
/* 313 */           query.append("*");
/* 314 */         query.append(this.mText);
/* 315 */         if ((this.mMatch == Filter.MatchType.contains) || (this.mMatch == Filter.MatchType.starts_with))
/* 316 */           query.append("*");
/* 317 */         ZimbraLog.dav.debug("Gal query: %s", new Object[] { query.toString() });
/*     */         
/* 319 */         GalSearchParams params = new GalSearchParams(ctxt.getAuthAccount());
/* 320 */         params.setType(GalSearchType.account);
/* 321 */         params.setQuery(query.toString());
/* 322 */         params.setResultCallback(new Callback(ctxt, result, params));
/* 323 */         GalSearchControl gal = new GalSearchControl(params);
/*     */         try {
/* 325 */           gal.search();
/*     */         } catch (ServiceException e) {
/* 327 */           if ("service.PERM_DENIED".equals(e.getCode())) {
/* 328 */             ZimbraLog.dav.debug("Can't get gal search result for %s (%s)", new Object[] { ctxt.getUser(), e.getMessage() });
/*     */           } else
/* 330 */             ZimbraLog.dav.error("Can't get gal search result for %s", new Object[] { ctxt.getUser() });
/*     */         }
/*     */       }
/* 333 */       return result;
/*     */     }
/*     */   }
/*     */   
/*     */   public static class ParamFilter extends Filter {
/* 338 */     public ParamFilter(org.dom4j.Element elem, Filter parent) { super(); }
/*     */     
/*     */     public boolean match(String prop) {
/* 341 */       return runTextMatch(prop);
/*     */     }
/*     */     
/*     */     protected boolean canHavePropFilter() {
/* 345 */       return false;
/*     */     }
/*     */     
/* 348 */     protected boolean canHaveParamFilter() { return false; }
/*     */   }
/*     */   
/*     */   public static class PropFilter extends Filter {
/* 352 */     public PropFilter(org.dom4j.Element elem) { super(); }
/*     */     
/*     */     public boolean match(Contact contact) {
/* 355 */       String val = contact.get(this.mName);
/* 356 */       if (val == null)
/* 357 */         return this.mIsNotDefinedSet;
/* 358 */       boolean matched = true;
/* 359 */       for (Filter.ParamFilter pf : this.mParams)
/* 360 */         matched &= pf.match(val);
/* 361 */       matched &= runTextMatch(val);
/* 362 */       return matched;
/*     */     }
/*     */     
/*     */     public Collection<AddressObject> match(DavContext ctxt, AddressbookCollection folder)
/*     */     {
/* 367 */       if (!this.mIsNotDefinedSet)
/*     */       {
/*     */ 
/* 370 */         if (this.mTextMatch != null)
/* 371 */           return this.mTextMatch.match(ctxt, folder);
/* 372 */         if (this.mParams != null) {
/* 373 */           ArrayList<AddressObject> result = new ArrayList();
/* 374 */           for (Filter.ParamFilter f : this.mParams)
/* 375 */             result.addAll(f.match(ctxt, folder));
/* 376 */           return result;
/*     */         } }
/* 378 */       return null;
/*     */     }
/*     */     
/*     */     protected boolean canHavePropFilter() {
/* 382 */       return false;
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/dav/carddav/Filter.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */